<template>
  <el-dialog width="1246px" top="3vh" :close-on-click-modal="false" :show-close="false" v-model="dialogVisible"
    class="CourseAppointment" @closed="cancel" @open="dialogOpen">
    <template #header>
      <div class="header">宣讲课程{{ type ? '修改' : '预约' }}</div>
    </template>
    <div v-loading="submitLoading" class="appointment-main">
      <el-scrollbar view-style="padding-right: 14px;" height="100%">
        <div class="common-title">课程日期预约</div>
        <div class="calendar main-wrapper">
          <div class="current-date">
            <el-icon @click="preMonthACtion" class="pre">
              <CaretLeft />
            </el-icon>
            <div class="show-date">{{ current.format('YYYY年 MM月') }}</div>
            <el-icon @click="nextMonthACtion" class="next">
              <CaretRight />
            </el-icon>
          </div>
          <div class="week">
            <div>一</div>
            <div>二</div>
            <div>三</div>
            <div>四</div>
            <div>五</div>
            <div>六</div>
            <div>日</div>
          </div>
          <div v-loading="radioLoading" class="date-list">
            <div :class="['date-item', appointTime == calItem.dayStr ? 'active-date' : '', handleDateStyle(calItem)]"
              v-for="(calItem, calIndex) in  calendarList" :key="calIndex" @click="selectDate(calItem)">
              {{ handleDateShow(calItem) }}
            </div>
          </div>
        </div>
        <el-form class="modelForm" ref="modelFormRef" label-position="top" :rules="rules" :model="model">
          <div class="common-title">预约课程时间</div>
          <div class="main-wrapper" v-loading="radioLoading">
            <el-form-item label="场次：" prop="timeType">
              <el-radio-group v-model="model.timeType">
                <el-radio :label="0" :disabled="!isMorningChoose">
                  上午场
                  <span v-if="morningTips">{{ morningTips }}</span>
                </el-radio>
                <el-radio :label="1" :disabled="!isAfternoonChoose">
                  下午场
                  <span v-if="afternoonTips">{{ afternoonTips }}</span>
                </el-radio>
              </el-radio-group>
            </el-form-item>
          </div>
          <div v-if="type != 'expertModify'" class="common-title">预约课程信息</div>
          <div v-if="type != 'expertModify'" class="main-wrapper">
            <el-form-item label="地点：" prop="location">
              <el-input v-model="model.location" size="large" @change="locationChange" placeholder="请输入地点，回车以获取具体位置" />

              <div id="reservation-map" class="location-c"></div>
            </el-form-item>
            <el-form-item label="听众人数：" prop="listenerCount">
              <el-input-number step-strictly :step="1" v-model="model.listenerCount" :min="1" controls-position="right"
                style="width: 100%;" size="large" />
            </el-form-item>
            <el-form-item label="联系人：" prop="linkMan">
              <el-input v-model="model.linkMan" size="large" />
            </el-form-item>
            <el-form-item label="联系人电话：" prop="linkManTel">
              <el-input v-model.number="model.linkManTel" size="large" />
            </el-form-item>
            <el-form-item label="申请单位：" prop="applicants">
              <el-input v-model="model.applicants" size="large" />
            </el-form-item>
            <el-form-item label="预约说明：" prop="appointDescribe">
              <el-input v-model="model.appointDescribe" type="textarea" rows="6" resize="none" />
            </el-form-item>
          </div>
        </el-form>
      </el-scrollbar>
    </div>
    <template #footer>
      <div class="footer">
        <el-button size="large" text bg round @click="dialogVisible = false">取 消</el-button>
        <el-button size="large" type="primary" @click="submit" round>提 交</el-button>
      </div>
    </template>
  </el-dialog>
</template>
<script>
/**
 * 课程预约组件
 * 
 **/
export default { name: 'CourseAppointment' }
</script>
<script setup>
import { computed, reactive, ref, watch } from 'vue';
import { CaretLeft, CaretRight } from '@element-plus/icons-vue'
import moment, { format } from '@/plugins/moment.js'
import { getCalendar } from '@/utils/index.js'
import { http } from '@/utils/http/index.js'
import { ElMessage } from 'element-plus';
import { useRouter } from 'vue-router';
import { useAuthStore } from '@/stores/modules/auth.js';
import axios from 'axios';

const router = useRouter()
const authStore = useAuthStore()

const props = defineProps(['visible', 'courseId', 'expertId', 'courseName', 'type', 'orderId'])
const emit = defineEmits(['update:visible', 'callback'])
/**双向绑定 */
const dialogVisible = computed({
  get() {
    return props.visible
  },
  set(value) {
    emit('update:visible', value)
  }
})

const current = ref(moment())
const appointTime = ref('')
const calendarList = ref([])

watch(dialogVisible, () => {
  if (dialogVisible.value && authStore.isExpired(true)) return dialogVisible.value = false
  if (dialogVisible.value) {
    clearSelect()
    /**专家修改表单回显 */
    if (props.type == 'expertModify') {
      _GetPreachOrderDetail()
      return
    }
    current.value = moment()
    calendarList.value = getCalendar(current.value)
    getCourseIsReservation()
  }
})

const clearSelect = () => {
  appointTime.value = ''
  model.timeType = ''
  isMorningChoose.value = false
  isAfternoonChoose.value = false
  morningTips.value = ''
  afternoonTips.value = ''
}


/* 上午可预约状态 */
const isMorningChoose = ref(false)
const morningTips = ref("")
/* 下午可预约状态 */
const isAfternoonChoose = ref(false)
const afternoonTips = ref("")

/**选定日期 */
const selectDate = (calItem) => {
  const isPast = moment(calItem.dayStr) < moment(moment().format('YYYY-MM-DD'))
  if (isPast || !calItem.isCurrentMonth) return
  if (!calItem.possibility) return
  appointTime.value = calItem.dayStr
  model.timeType = ''
  isMorningChoose.value = calItem.morningStatus
  isAfternoonChoose.value = calItem.afternoonStatus
  // 处理时间单选框
  if (isPast) {
    morningTips.value = '不可预约'
    afternoonTips.value = '不可预约'
    return
  }
  morningTips.value = !calItem.possibility
    ? '已约满'
    : !calItem.morningStatus ? '不可预约' : ''
  afternoonTips.value = !calItem.possibility
    ? '已约满'
    : !calItem.afternoonStatus ? '不可预约' : ''
}
const preMonthACtion = () => {
  current.value = current.value.clone().subtract(1, 'months')
  clearSelect()
  calendarList.value = getCalendar(current.value)
  getCourseIsReservation()
}
const nextMonthACtion = () => {
  current.value = current.value.clone().add(1, 'months')
  clearSelect()
  calendarList.value = getCalendar(current.value)
  getCourseIsReservation()
}
const handleDateShow = (date) => {
  if (moment(date.dayStr) < moment(moment().format('YYYY-MM-DD')) || !date.isCurrentMonth || date.weekOfDay == 6 || date.weekOfDay == 0) return date.day
  if (!date.possibility) return '约满'
  return date.day
}
// 处理当前日期展示效果
const handleDateStyle = (date) => {
  if (moment(date.dayStr) < moment(moment().format('YYYY-MM-DD')) || !date.isCurrentMonth || date.weekOfDay == 6 || date.weekOfDay == 0) return 'not-current-m'
  // 当天约满
  if (!date.possibility) return 'fully'
}

/* 查询当前日期场次是否支持预约 */
const radioLoading = ref(false)
const getCourseIsReservation = () => {
  return new Promise(resolve => {
    radioLoading.value = true
    const params = {
      expertId: props.expertId,
      appointTime: current.value.clone().format('YYYY-M'),
      courseId: props.courseId
    }
    http.$GET("/Preach/GetPreachExpertCourse_IsReservation", params).then(res => {
      if (!res.isError) return ElMessage.warning("查询失败")
      const tempList = res.result
      calendarList.value = calendarList.value.map(el => {
        let morningStatus = false
        let afternoonStatus = false
        let possibility = false
        const find = tempList.find(fi => moment(fi.date).format('YYYY-MM-DD') == moment(el.dayStr).format('YYYY-MM-DD'))
        if (find) {
          morningStatus = find.morningStatus
          afternoonStatus = find.afternoonStatus
          possibility = find.status
        }
        /**临时课程不需要禁用*/
        if (props.type == 'baseCourse') {
          morningStatus = true
          afternoonStatus = true
          possibility = true
        }
        return {
          ...el,
          morningStatus,
          afternoonStatus,
          possibility
        }
      })
      resolve()
    }).catch(() => {
      radioLoading.value = false
      ElMessage.warning("查询失败")
      resolve()
    }).finally(() => radioLoading.value = false)
  })
}

/**预约表单 */
const model = reactive({
  location: '',
  listenerCount: 1,
  linkMan: '',
  linkManTel: '',
  appointDescribe: '',
  timeType: ''
})

const validatePhoneNum = (_, value, callback) => {
  // 判断是否为空  
  if (!value) callback(new Error('请输入联系人电话'))
  // 判断手机号格式是否正确  
  const regex = /^1[3-9]\d{9}$/; // 中国手机号的正则表达式  
  if (!regex.test(value)) {
    callback(new Error('手机号格式不正确'))
  }
  callback()
}

const rules = reactive({
  timeType: [{ required: true, message: '请选择课程场次', trigger: 'blur' }],
  location: [{ required: true, message: '请输入地点', trigger: 'blur' }],
  listenerCount: [{ required: true, message: '请输入听众人数', trigger: 'blur' }],
  linkMan: [{ required: true, message: '请输入联系人', trigger: 'blur' }],
  linkManTel: [{ type: 'number', message: '请输入数字' }, { required: true, trigger: 'blur', validator: validatePhoneNum }],
  appointDescribe: [{ required: true, message: '请输入预约说明', trigger: 'blur' }],
  applicants: [{ required: true, message: '请输入申请单位', trigger: 'blur' }],
})

const modelFormRef = ref(null)
const cancel = () => {
  Object.keys(model).forEach(key => model[key] = '')
  model.listenerCount = 1
  appointTime.value = ''
  modelFormRef.value.clearValidate()
  baduScript && baduScript.remove()
}

const submitLoading = ref(false)
const submit = () => {
  // 表单校验
  modelFormRef.value.validate(valid => {
    if (!valid) return
    // 参数校验
    if (!props.courseId || !props.expertId || !props.courseName) return ElMessage.warning('缺少必要参数')
    if (!appointTime.value) return ElMessage.warning('请选择预约日期')
    if (props.type == 'expertModify') {
      return expertModifySubmit()
    }
    submitLoading.value = true
    const submitModel = JSON.parse(JSON.stringify(model))
    submitModel.listenerCount = submitModel.listenerCount + ''
    submitModel.linkManTel = submitModel.linkManTel + ''
    http.$POST('/Preach/AddPreachOrder', {
      uid: authStore.userInfo.uid,
      appointTime: appointTime.value,
      courseId: props.courseId,
      expertId: props.expertId,
      courseName: props.courseName,
      longitude: `${reservationLng.value}`,
      latitude: `${reservationLat.value}`,
      area: reservationDistrict.value,
      ...submitModel
    }).then(res => {
      if (res.isError) return
      ElMessage.success(res.message)
      dialogVisible.value = false
      router.push('/explain-and-publicize/appointment-successful?id=' + res.result)
    }).finally(() => submitLoading.value = false)
  })
}

// 专家修改
const expertModifySubmit = () => {
  if (model.timeType === '') return ElMessage.info('请选择预约时间')
  submitLoading.value = true
  http.$POST('/PreachM/EditPreachOrderByExpert', {
    orderId: props.orderId,
    appointTime: appointTime.value,
    timeType: model.timeType
  }).then(res => {
    ElMessage({
      type: res.isError ? 'error' : 'success',
      message: res.message
    })
    if (res.isError) return
    dialogVisible.value = false
    emit('callback')
  })
}

/**查询订单信息 */
const _GetPreachOrderDetail = () => {
  http.$GET('/Preach/GetPreachOrderDetail', { id: props.orderId }).then(res => {
    if (res.isError) return
    const tempModel = res.result
    appointTime.value = format(tempModel.order.appointTime)
    model.timeType = tempModel.order.timeType
    current.value = moment(appointTime.value)
    calendarList.value = getCalendar(current.value)
    getCourseIsReservation().then(() => {
      const find = calendarList.value.find(el => el.dayStr == appointTime.value)
      isMorningChoose.value = find.morningStatus
      isAfternoonChoose.value = find.afternoonStatus
      morningTips.value = !find.possibility
        ? '已约满'
        : !find.morningStatus ? '不可预约' : ''
      afternoonTips.value = !find.possibility
        ? '已约满'
        : !find.afternoonStatus ? '不可预约' : ''
    })
  })
}

let baduScript = ''
if (props.type != 'expertModify') {
  baduScript = document.createElement('script');
  baduScript.id = 'reservation-map'
  baduScript.type = 'text/javascript'
  baduScript.src = `https://api.map.baidu.com/getscript?type=webgl&v=1.0&ak=${import.meta.env.VITE_APP_BAIDU_MAP_AK}`
  document.body.appendChild(baduScript);
}

/* 地图部分 */
let reservationMap;
const reservationLat = ref(null) /* 所选地点纬度 */
const reservationLng = ref(null) /* 所选地点经度 */
const reservationDistrict = ref(null) /* 所选地点所属区划 */

const setBaiduIns = () => {
  // eslint-disable-next-line no-undef
  reservationMap = new BMapGL.Map("reservation-map")
  reservationMap.enableScrollWheelZoom(true);

  // eslint-disable-next-line no-undef
  const point = new BMapGL.Point(114.311754, 30.598604)
  reservationMap.centerAndZoom(point, 11)

  // eslint-disable-next-line no-undef
  var marker2 = new BMapGL.Marker(point);
  //在地图上添加点标记
  reservationMap.addOverlay(marker2);
}

/* 打开弹窗时加载百度地图 */
const dialogOpen = () => {
  if (props.type == 'expertModify') return
  if (!reservationMap) {
    setBaiduIns()

    if (baduScript.readyState) {
      baduScript.onreadystatechange = () => {
        if (baduScript.readyState === "complete" || baduScript.readyState === 'loaded') {
          setBaiduIns()
        }
      }
    } else {
      baduScript.onload = setBaiduIns
    }
  }
}

/* 地点变化 */
const locationChange = (val) => {
  //在地图上添加点标记

  var allOverlay = reservationMap.getOverlays();
  reservationMap.removeOverlay(allOverlay[allOverlay.length - 1]);

  /* 获取输入地点的经纬度 */
  const url = `/baidu/geocoding/v3/?address=${val}&output=json&ak=${import.meta.env.VITE_APP_SERVER_MAP_AK}`

  axios.get(url).then((res) => {

    reservationLng.value = res.data.result.location.lng
    reservationLat.value = res.data.result.location.lat

    // eslint-disable-next-line no-undef
    const point = new BMapGL.Point(res.data.result.location.lng, res.data.result.location.lat)
    reservationMap.centerAndZoom(point, 11)

    // eslint-disable-next-line no-undef
    var marker2 = new BMapGL.Marker(point);
    //在地图上添加点标记
    reservationMap.addOverlay(marker2);

    /* 通过经纬度逆向获取行政区划 */
    const url = `/baidu/reverse_geocoding/v3/?ak=${import.meta.env.VITE_APP_SERVER_MAP_AK}&output=json&coordtype=wgs84ll&location=${res.data.result.location.lat},${res.data.result.location.lng}`

    axios.get(url).then(_res => {
      reservationDistrict.value = _res.data.result.addressComponent.district
    })
  })
}


</script>
<style lang='scss' scoped>
.CourseAppointment {

  .header {
    font-size: 26px;
    font-weight: 500;
    color: #000000;
  }

  .appointment-main {
    font-family: PingFang SC-Medium, PingFang SC;
    width: 100%;
    height: 72vh;
    padding-bottom: 30px;

    .main-wrapper {
      width: 80%;
      margin: 0 auto;
    }

    .common-title {
      width: 100%;
      height: 40px;
      background: #F8F8F8;
      font-size: 16px;
      font-weight: 500;
      color: #000000;
      padding-left: 19px;
      display: flex;
      align-items: center;
      position: relative;
      margin-bottom: 26px;

      &::before {
        content: '';
        position: absolute;
        left: 0;
        top: 8px;
        bottom: 7px;
        width: 4px;
        background-color: var(--theme-color);
      }
    }

    .calendar {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      user-select: none;
      margin-bottom: 49px;

      .current-date {
        margin-bottom: 25px;
        font-size: 20px;
        color: #0A1629;
        display: flex;
        align-items: center;
        gap: 28px;

        .pre,
        .next {
          color: var(--theme-color);
          cursor: pointer;
        }

        .show-date {
          cursor: pointer;
        }
      }

      .week {
        width: 100%;
        height: 48px;
        background: #FAF8F8;
        font-size: 22px;
        font-weight: 600;
        color: #42434D;
        display: grid;
        grid-template-columns: repeat(7, 59px);
        grid-column-gap: 81px;
        margin-bottom: 32px;

        >div {
          display: flex;
          justify-content: center;
          align-items: center;
        }
      }

      .date-list {
        width: 100%;
        display: grid;
        grid-template-columns: repeat(7, 59px);
        grid-column-gap: 81px;
        grid-row-gap: 13px;

        .date-item {
          width: 100%;
          height: 54px;
          display: flex;
          align-items: center;
          justify-content: center;
          border-radius: 50%;
          transition: all .2s;
          font-size: 18px;
          cursor: pointer;
          color: #2F2F2F;
          font-weight: bold;

          &.not-current-m {
            color: #898989;
          }

          &.fully {
            background-color: #ECECEC;
            color: #B9B9B9;
            font-weight: 500;
            font-size: 19px;
          }

          &:not(.not-current-m, .fully):hover,
          &.active-date {
            background-color: var(--theme-color);
            color: #fff;
          }

          &.not-current-m,
          &.fully {
            cursor: not-allowed;
          }
        }
      }
    }

    .timeForm {
      :deep(.el-form-item__label) {
        font-size: 17px;
        color: #0A1629 !important;
      }

      :deep(.el-radio__label) {
        font-size: 17px;
      }

      :deep(.el-radio__inner) {
        width: 16px;
        height: 16px;
      }

      :deep(.el-date-editor--time) {
        width: 156px;
      }
    }

    .modelForm {
      :deep(.el-form-item__label) {
        font-size: 17px;
        color: #000 !important;
      }

      :deep(.el-input) {
        // height: 40px;

        .el-input__wrapper {
          background-color: #FAF8F8;
        }
      }

      :deep(.el-textarea__inner) {
        background-color: #FAF8F8;
      }
    }

  }

  .footer {
    display: flex;
    justify-content: center;
    gap: 14px;

    :deep(.el-button) {
      width: 115px;
      height: 43px;
      line-height: unset;
      border-radius: 25px;
    }
  }
}

.location-c {
  height: 300px;
  width: 100%;
  margin-top: 10px;

  :deep(.BMap_cpyCtrl) {
    span {
      // display: none !important;
      font-size: 12px;
    }
  }
}
</style>
<style>
.CourseAppointment {
  margin-bottom: 30px;

  .el-dialog__header {
    padding-left: 54px;
  }

  .el-dialog__body {
    padding-left: 54px;
    padding-right: 50px;
    padding-bottom: 10px;
  }
}
</style>